package com.yanyeori.framework.core.util;

import com.yanyeori.framework.core.constant.BaseConstant;
import org.apache.commons.collections4.map.CaseInsensitiveMap;
import org.apache.commons.lang3.ArrayUtils;
import org.springframework.lang.Nullable;
import org.springframework.web.bind.ServletRequestBindingException;
import org.springframework.web.bind.ServletRequestUtils;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.IOException;
import java.io.PrintWriter;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Servlet工具类
 */
public class ServletUtil {
    /**
     * 获取String参数
     */
    public static String getParameter(String name) {
        return getRequest().getParameter(name);
    }

    /**
     * 获取String参数
     */
    public static String getParameter(String name, String defaultVal) {
        return ServletRequestUtils.getStringParameter(getRequest(), name, defaultVal);
    }

    /**
     * 获取Integer参数
     */
    public static Integer getIntParameter(String name) {
        try {
            return ServletRequestUtils.getIntParameter(getRequest(), name);
        } catch (ServletRequestBindingException e) {
            return null;
        }
    }

    /**
     * 获取Integer参数
     */
    public static Integer getIntParameter(String name, int defaultVal) {
        return ServletRequestUtils.getIntParameter(getRequest(), name, defaultVal);
    }

    /**
     * 获取Long参数
     */
    public static Long getLongParameter(String name) {
        try {
            return ServletRequestUtils.getLongParameter(getRequest(), name);
        } catch (ServletRequestBindingException e) {
            return null;
        }
    }

    /**
     * 获取Long参数
     */
    public static Long getLongParameter(String name, long defaultVal) {
        return ServletRequestUtils.getLongParameter(getRequest(), name, defaultVal);
    }

    /**
     * 获取Double参数
     */
    public static Double getDoubleParameter(String name) {
        try {
            return ServletRequestUtils.getDoubleParameter(getRequest(), name);
        } catch (ServletRequestBindingException e) {
            return null;
        }
    }

    /**
     * 获取Double参数
     */
    public static Double getDoubleParameter(String name, double defaultVal) {
        return ServletRequestUtils.getDoubleParameter(getRequest(), name, defaultVal);
    }

    /**
     * 获取Boolean参数
     */
    public static Boolean getBooleanParameter(String name) {
        try {
            return ServletRequestUtils.getBooleanParameter(getRequest(), name);
        } catch (ServletRequestBindingException e) {
            return null;
        }
    }

    /**
     * 获取Boolean参数
     */
    public static Boolean getBooleanParameter(String name, boolean defaultVal) {
        return ServletRequestUtils.getBooleanParameter(getRequest(), name, defaultVal);
    }

    /**
     * 获得所有请求参数
     *
     * @return Map
     */
    public static Map<String, String[]> getParameterMap() {
        return Collections.unmodifiableMap(getRequest().getParameterMap());
    }

    /**
     * 获取Headers
     */
    public static Map<String, String> getHeaderMap() {
        Map<String, String> map = new CaseInsensitiveMap<>();
        HttpServletRequest request = getRequest();
        Enumeration<String> headerNames = request.getHeaderNames();
        while (headerNames.hasMoreElements()) {
            String headerName = headerNames.nextElement();
            String headerValue = request.getHeader(headerName);
            map.put(headerName, headerValue);
        }
        return map;
    }

    /**
     * 获取session
     */
    public static HttpSession getSession() {
        return getRequest().getSession();
    }

    /**
     * 获取Cookies
     */
    public static Cookie[] getCookies() {
        return getRequest().getCookies();
    }

    /**
     * 获取Cookies map
     */
    public static Map<String, String> getCookiesMap() {
        Cookie[] cookies = getCookies();
        if (ArrayUtils.isEmpty(cookies)) return new HashMap<>();
        return Arrays.stream(cookies).collect(Collectors.toMap(Cookie::getName, Cookie::getValue, (v1, v2) -> v2, CaseInsensitiveMap::new));
    }

    /**
     * 获取指定Cookie值
     */
    public static String getCookieValue(String name) {
        return getCookiesMap().get(name);
    }

    /**
     * 设定返回给客户端的Cookie
     *
     * @param name  cookie名
     * @param value cookie值
     */
    public static void addCookie(String name, String value) {
        addCookie(new Cookie(name, value));
    }

    /**
     * 设定返回给客户端的Cookie
     *
     * @param name            cookie名
     * @param value           cookie值
     * @param maxAgeInSeconds -1: 关闭浏览器清除Cookie. 0: 立即清除Cookie. >0 : Cookie存在的秒数.
     * @param path            Cookie的有效路径
     * @param domain          the domain name within which this cookie is visible; form is according to RFC 2109
     */
    public static void addCookie(String name, String value, int maxAgeInSeconds, @Nullable String path, @Nullable String domain) {
        Cookie cookie = new Cookie(name, value);
        cookie.setMaxAge(maxAgeInSeconds);
        cookie.setPath(StringUtil.isEmpty(path) ? "/" : path);
        if (domain != null) {
            cookie.setDomain(domain);
        }
        addCookie(cookie);
    }

    /**
     * 设定返回给客户端的Cookie
     *
     * @param cookie Servlet Cookie对象
     */
    public static void addCookie(Cookie cookie) {
        getResponse().addCookie(cookie);
    }

    /**
     * 获取请求的User-Agent
     */
    public static String getUserAgent() {
        return getRequest().getHeader("User-Agent");
    }

    /**
     * 判断是否Safari浏览器
     */
    public static boolean isSafariBrowser() {
        String userAgent = getUserAgent();
        return StringUtil.isNotEmpty(userAgent) && StringUtil.containsIgnoreCase(userAgent, "safari")
                && !StringUtil.containsIgnoreCase(userAgent, "chrome");
    }

    /**
     * 判断是否Chrome浏览器
     */
    public static boolean isChromeBrowser() {
        String userAgent = getUserAgent();
        return StringUtil.isNotEmpty(userAgent) && StringUtil.containsIgnoreCase(userAgent, "chrome");
    }

    /**
     * 判断是否IE浏览器
     */
    public static boolean isIEBrowser() {
        String userAgent = getUserAgent();
        return StringUtil.isNotEmpty(userAgent) && StringUtil.containsIgnoreCase(userAgent, "msie");
    }

    /**
     * 获取客户端IP
     *
     * @param otherHeaderNames 其他自定义header
     * @return IP地址
     */
    public static String getClientIP(String... otherHeaderNames) {
        return HttpUtil.getClientIP(getRequest(), otherHeaderNames);
    }

    /**
     * 向response中写入渲染信息
     */
    public static void writeToResponse(int status, Object msg) {
        writeToResponse(getResponse(), status, msg);
    }

    /**
     * 向response中写入渲染信息
     */
    public static void writeToResponse(HttpServletResponse response, int status, Object msg) {
        response.setStatus(status);
        response.setCharacterEncoding(BaseConstant.UTF_8);
        response.setContentType(BaseConstant.CONTENT_TYPE_JSON);
        if (msg == null) return;
        try (PrintWriter printWriter = response.getWriter()) {
            printWriter.write(msg instanceof String ? msg.toString() : JacksonUtil.toJson(msg));
            printWriter.flush();
        } catch (IOException e) {
            //printWriter IOException
        }
    }

    /**
     * 向request的Attribute中写入属性值信息
     */
    public static void writeAttributeToRequest(String key, String message) {
        writeAttributeToRequest(getRequest(), key, message);
    }

    /**
     * 向request的Attribute中写入属性值信息
     */
    public static void writeAttributeToRequest(HttpServletRequest request, String key, String message) {
        if (request != null && StringUtil.isNotEmpty(key)) {
            request.setAttribute(key, message);
        }
    }

    /**
     * 读取request的Attribute中指定属性值信息
     */
    public static String readAttributeFromRequest(String key) {
        return readAttributeFromRequest(getRequest(), key);
    }

    /**
     * 读取request的Attribute中指定属性值信息
     */
    public static String readAttributeFromRequest(HttpServletRequest request, String key) {
        if (request != null && StringUtil.isNotEmpty(key)) {
            Object attribute = request.getAttribute(key);
            return attribute == null ? null : attribute.toString();
        }
        return null;
    }

    /**
     * 获取request
     */
    public static HttpServletRequest getRequest() {
        return getRequestAttributes().getRequest();
    }

    /**
     * 获取response
     */
    public static HttpServletResponse getResponse() {
        return getRequestAttributes().getResponse();
    }

    public static ServletRequestAttributes getRequestAttributes() {
        return (ServletRequestAttributes) RequestContextHolder.getRequestAttributes();
    }
}
